//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include "pcentral.h"
#include "request.h"
#include "protocol.h"
#include "pseudo.h"
#include "ipcchannel.h"
#include <aura.h>

#define CENTRAL_CHANNEL L"ElCentral"

STATIC CChannelPool * s_pChannelPool = NULL;
STATIC ProcessId GetCurrentProcessId()
{
    STATIC ProcessId processId = AURA_INVALID_PID;
    if (AURA_INVALID_PID != processId) {
        return processId;
    }
    CPseudoKernel::Process_GetCurrentId(&processId);
    return processId;
}

INLINE ECode InvokeRequest(
    /* [in] */ InvokeFuncPTR invokeFunc,
    /* [in] */ PVoid pArgs)
{
    ECode result = NOERROR;
    ECode ec = NOERROR;
    assert(NULL != s_pChannelPool);

    ec = s_pChannelPool->Invoke(invokeFunc, pArgs, &result);
    return (FAILED(ec) ? ec : result);
}

ECode PseudoCentral_Initialize()
{
    ECode ec = NOERROR;

    s_pChannelPool = new CChannelPool();
    if (NULL == s_pChannelPool) {
        return E_OUT_OF_MEMORY;
    }
    ec = s_pChannelPool->Initialize(CENTRAL_CHANNEL);
    if (FAILED(ec)) {
        delete s_pChannelPool;
        s_pChannelPool = NULL;
    }
    return ec;
}

void PseudoCentral_Destroy()
{
    if (NULL != s_pChannelPool) {
        delete s_pChannelPool;
        s_pChannelPool = NULL;
    }
    return ;
}

// ----- For CPseudoProcess -------------------

ECode CPseudoCentral::Process_Create(
    /* [in] */ ThreadPriorityRank priorityRank,
    /* [in] */ Int32 capacity,
    /* [in] */ WString name,
    /* [in] */ WString args,
    /* [out] */ ProcessId * pProcessId)
{
    ECode ec = NOERROR;

    assert(!name.IsNullOrEmpty());
    assert(NULL != pProcessId);

    Int32 nameLength = name.GetLength(AURA_MAX_PATH) + 1;
    Int32 argsLength = args.GetLength(AURA_MAX_PATH) + 1;

    SERVER_START_REQ(start_process)
    {
        req->requestPid = GetCurrentProcessId();
        req->priorityRank = priorityRank;
        req->capacity= capacity;
        add_request_data(req, (const wchar_t *)name, nameLength * sizeof(wchar_t));
        add_request_data(req, (const wchar_t *)args, argsLength * sizeof(wchar_t));
        ec = InvokeRequest(central_call, req);
        if (SUCCEEDED(ec)) {
            *pProcessId = reply->processId;
        }
    }
    SERVER_END_REQ;

    return ec;
}

ECode CPseudoCentral::Process_Open(
    /* [in] */ WString name,
    /* [in] */ WString args,
    /* [in] */ ProcessId processId)
{
    ECode ec = NOERROR;
    assert(!name.IsNullOrEmpty());

    Int32 nameLength = name.GetLength(AURA_MAX_PATH) + 1;
    Int32 argsLength = args.GetLength(AURA_MAX_PATH) + 1;

    SERVER_START_REQ(create_gprocess)
    {
        req->processId = processId;
        add_request_data(req, (const wchar_t *)name, nameLength * sizeof(wchar_t));
        add_request_data(req, (const wchar_t *)args, argsLength * sizeof(wchar_t));
        ec = InvokeRequest(central_call, req);
    }
    SERVER_END_REQ;

    return ec;
}

ECode CPseudoCentral::Process_Kill(
    /* [in] */ ProcessId processId,
    /* [in] */ ExitCode exitCode)
{
    ECode ec = NOERROR;

    SERVER_START_REQ(kill_process)
    {
        req->processId = processId;
        req->exitCode = exitCode;
        ec = InvokeRequest(central_call, req);
    }
    SERVER_END_REQ;

    return ec;
}

ECode CPseudoCentral::Process_Release(
            /* [in] */ ProcessId processId)
{
    ECode ec = NOERROR;

    SERVER_START_REQ(release_process)
    {
        req->requestPid = GetCurrentProcessId();
        req->processId = processId;
        ec = InvokeRequest(central_call, req);
    }
    SERVER_END_REQ;

    return ec;
}

ECode CPseudoCentral::Process_GetStartInfo(
    /* [in] */ ProcessId processId,
    /* [out] */ WStringBuf * pName,
    /* [out] */ WStringBuf * pArgs)
{
    ECode ec = NOERROR;

    assert((NULL != pName) && pName->GetCapacity());
    assert((NULL != pArgs) && pArgs->GetCapacity());

    Int32 nameLength = (pName->GetCapacity() + 1);
    Int32 argsLength = (pArgs->GetCapacity() + 1);

    SERVER_START_REQ(get_process_startInfo)
    {
        req->processId = processId;
        add_reply_data(req, pName->GetPayload(), nameLength * sizeof(wchar_t));
        add_reply_data(req, pArgs->GetPayload(), argsLength * sizeof(wchar_t));
        ec = InvokeRequest(central_call, req);
    }
    SERVER_END_REQ;

    return ec;
}

ECode CPseudoCentral::Process_WaitForExit(
    /* [in] */ ProcessId processId,
    /* [in] */ Millisecond32 timeout,
    /* [out] */ WaitResult * pResult)
{
    ECode ec = NOERROR;
    assert(NULL != pResult);

    SERVER_START_REQ( waitfor_process_toexit )
    {
        req->processId = processId;
        req->timeOut = timeout;
        ec = InvokeRequest(central_call, req);
        if (SUCCEEDED(ec)) {
            *pResult = reply->waitResult;
        }
    }
    SERVER_END_REQ;
    return ec;
}

ECode CPseudoCentral::Process_IsAlive(
    /* [in] */ ProcessId processId,
    /* [out] */ Boolean * pIsAlive)
{
    ECode ec = NOERROR;
    assert(NULL != pIsAlive);

    SERVER_START_REQ( process_IsAlive)
    {
        req->processId = processId;
        ec = InvokeRequest(central_call, req);
        if (SUCCEEDED(ec)) {
            *pIsAlive = reply->bIsAlive;
        }
    }
    SERVER_END_REQ;

    return ec;
}

ECode CPseudoCentral::Process_GetExitCode(
            /* [in] */ ProcessId processId,
            /* [out] */ ExitCode * pExitCode)
{
    ECode ec = NOERROR;

    assert(NULL != pExitCode);

    SERVER_START_REQ(get_process_exitCode)
    {
        req->processId = processId;
        ec = InvokeRequest(central_call, req);
        if (SUCCEEDED(ec)) {
            *pExitCode = reply->exitCode;
        }
    }
    SERVER_END_REQ;

    return ec;
}

ECode CPseudoCentral::Process_GetStartTime(
    /* [in] */ ProcessId processId,
    /* [out]*/ SystemTime * pTime)
{
    ECode ec = NOERROR;

    assert(NULL != pTime);

    SERVER_START_REQ(get_process_startTime)
    {
        req->processId = processId;
        ec = InvokeRequest(central_call, req);
        if (SUCCEEDED(ec)) {
            *pTime = reply->time;
        }
    }
    SERVER_END_REQ;

    return ec;
}

ECode CPseudoCentral::Process_GetExitTime(
    /* [in] */ ProcessId processId,
    /* [out]*/ SystemTime * pTime)
{
    ECode ec = NOERROR;

    assert(NULL != pTime);

    SERVER_START_REQ(get_process_exitTime)
    {
        req->processId = processId;
        ec = InvokeRequest(central_call, req);
        if (SUCCEEDED(ec)) {
            *pTime = reply->time;
        }
    }
    SERVER_END_REQ;

    return ec;
}

ECode CPseudoCentral::Process_GetProcessorTimes(
    /* [in]  */ ProcessId processId,
    /* [out] */ Millisecond32 * pUserTime,
    /* [out] */ Millisecond32 * pPrivilegedTime)
{
    ECode ec = NOERROR;

    assert((NULL != pUserTime) || (NULL != pPrivilegedTime));
    SERVER_START_REQ(get_process_processorTimes)
    {
        req->processId = processId;
        ec = InvokeRequest(central_call, req);
        if (SUCCEEDED(ec)) {
            if (NULL != pUserTime) {
                *pUserTime = reply->userTime;
            }
            if (NULL != pPrivilegedTime) {
                *pPrivilegedTime = reply->privilegedTime;
            }
        }
    }
    SERVER_END_REQ;

    return ec;
}

ECode CPseudoCentral::Process_TransferInfo(
    /* [in] */ ProcessId processId,
    /* [in] */ ExitCode exitCode,
    /* [in] */ Millisecond32 userTime,
    /* [in] */ Millisecond32 privilegedTime)
{
    ECode ec = NOERROR;

    SERVER_START_REQ(transfer_process_info)
    {
        req->processId = processId;
        req->exitCode  = exitCode;
        req->userTime  = userTime;
        req->privilegedTime = privilegedTime;
        ec = InvokeRequest(central_call, req);
    }
    SERVER_END_REQ;

    return ec;
}


ECode CPseudoCentral::Thread_AddRef(
    /* [in] */ ThreadId threadId,
    /* [in] */ ProcessId hostPid)
{
    ECode ec = NOERROR;

    SERVER_START_REQ(addref_thread)
    {
        req->requestPid = GetCurrentProcessId();
        req->threadId = threadId;
        req->hostPid  = hostPid;
        ec = InvokeRequest(central_call, req);
    }
    SERVER_END_REQ;

    return ec;
}

ECode CPseudoCentral::Thread_Release(
    /* [in] */ ThreadId threadId)
{
    ECode ec = NOERROR;

    SERVER_START_REQ(release_thread)
    {
        req->requestPid = GetCurrentProcessId();
        req->threadId = threadId;
        ec = InvokeRequest(central_call, req);
    }
    SERVER_END_REQ;

    return ec;
}

ECode CPseudoCentral::Thread_GetQuitCode(
    /* [in] */ ThreadId threadId,
    /* [out] */ QuitCode * pQuitCode)
{
    ECode ec = NOERROR;

    assert(NULL != pQuitCode);

    SERVER_START_REQ(get_thread_quitCode)
    {
        req->threadId = threadId;
        ec = InvokeRequest(central_call, req);
        if (SUCCEEDED(ec)) {
            *pQuitCode = reply->quitCode;
        }
    }
    SERVER_END_REQ;

    return ec;
}

ECode CPseudoCentral::Thread_GetStartTime(
    /* [in] */ ThreadId threadId,
    /* [out] */ SystemTime * pTime)
{
    ECode ec = NOERROR;

    assert(NULL != pTime);

    SERVER_START_REQ(get_thread_startTime)
    {
        req->threadId = threadId;
        ec = InvokeRequest(central_call, req);
        if (SUCCEEDED(ec)) {
            *pTime = reply->time;
        }
    }
    SERVER_END_REQ;

    return ec;
}

ECode CPseudoCentral::Thread_GetQuitTime(
    /* [in] */ ThreadId threadId,
    /* [out] */ SystemTime * pTime)
{
    ECode ec = NOERROR;

    assert(NULL != pTime);

    SERVER_START_REQ(get_thread_quitTime)
    {
        req->threadId = threadId;
        ec = InvokeRequest(central_call, req);
        if (SUCCEEDED(ec)) {
            *pTime = reply->time;
        }
    }
    SERVER_END_REQ;

    return ec;
}

ECode CPseudoCentral::Thread_GetName(
    /* [in] */ ThreadId threadId,
    /* [out] */ WStringBuf * pName)
{
    ECode ec = NOERROR;

    assert((NULL != pName) && pName->GetCapacity());
    Int32 length = pName->GetCapacity() + 1;

    SERVER_START_REQ(get_thread_name)
    {
        req->threadId = threadId;
        add_reply_data(req, pName->GetPayload(), length * sizeof(wchar_t));
        ec = InvokeRequest(central_call, req);
    }
    SERVER_END_REQ;

    return ec;
}

ECode CPseudoCentral::Thread_TransferInfo(
    /* [in] */ ThreadId threadId,
    /* [in] */ QuitCode quitCode,
    /* [in] */ SystemTime startTime,
    /* [in] */ SystemTime quitTime,
    /* [in] */ WString name)
{
    Int32 length = name.GetLength(AURA_MAX_PATH) + 1;
    ECode ec = NOERROR;

    //clear all the apc queue to avoid current thread
    //being interrupted in InvokeRequest
    Aura_WaitResult wr;
    AuraThread_Sleep(0, &wr);

    SERVER_START_REQ(transfer_thread_info)
    {
        req->processId = GetCurrentProcessId();
        req->threadId = threadId;
        req->quitCode = quitCode;
        req->startTime = startTime;
        req->quitTime  = quitTime;
        add_request_data(req, (const wchar_t *)name, length * sizeof(wchar_t));
        ec = InvokeRequest(central_call, req);
    }
    SERVER_END_REQ;

    return ec;
}

ECode CPseudoCentral::Enumerator_Create(
    /* [in] */ Int32 * pEnumeratorId)
{
    ECode ec = NOERROR;

    assert(NULL != pEnumeratorId);

    SERVER_START_REQ(create_enumerator)
    {
        req->requestPid = GetCurrentProcessId();
        ec = InvokeRequest(central_call, req);
        if (SUCCEEDED(ec)) {
            *pEnumeratorId = reply->enumeratorId;
        }
    }
    SERVER_END_REQ;

    return ec;
}

ECode CPseudoCentral::Enumerator_Release(
    /* [in] */ Int32 enumeratorId)
{
    ECode ec = NOERROR;

    SERVER_START_REQ(release_enumerator)
    {
        req->requestPid = GetCurrentProcessId();
        req->enumeratorId = enumeratorId;
        ec = InvokeRequest(central_call, req);
    }
    SERVER_END_REQ;

    return ec;
}

ECode CPseudoCentral::Enumerator_GetCurrent(
    /* [in] */ Int32 enumeratorId,
    /* [out] */ ProcessId * pProcessId)
{
    ECode ec = NOERROR;

    assert(NULL != pProcessId);

    SERVER_START_REQ(get_current)
    {
        req->requestPid = GetCurrentProcessId();
        req->enumeratorId = enumeratorId;
        ec = InvokeRequest(central_call, req);
        if (SUCCEEDED(ec)) {
            *pProcessId = reply->processId;
        }
    }
    SERVER_END_REQ;

    return ec;
}

ECode CPseudoCentral::Enumerator_MoveNext(
    /* [in] */ Int32 enumeratorId,
    /* [out] */ Boolean * pbSucceeded)
{
    ECode ec = NOERROR;

    assert(NULL != pbSucceeded);
    *pbSucceeded = FALSE;

    SERVER_START_REQ(move_next)
    {
        req->enumeratorId = enumeratorId;
        ec = InvokeRequest(central_call, req);
        if (SUCCEEDED(ec)) {
            *pbSucceeded = reply->bSucceeded;
        }
    }
    SERVER_END_REQ;

    return ec;
}

ECode CPseudoCentral::Enumerator_Reset(
    /* [in] */ Int32 enumeratorId)
{
    ECode ec = NOERROR;

    SERVER_START_REQ(reset_enumerator)
    {
        req->enumeratorId = enumeratorId;
        ec = InvokeRequest(central_call, req);
    }
    SERVER_END_REQ;

    return ec;
}

// ----------- For CMutex ------------------------

CARAPI CPseudoCentral::CreateNamedMutex(
    /* [in]  */ WString name,
    /* [out] */ Boolean * pbAlreadyExists,
    /* [out] */ oid_t * pOid)
{
    ECode ec = NOERROR;

    assert(!name.IsNullOrEmpty());
    assert(NULL != pbAlreadyExists);
    Int32 Length = name.GetLength(AURA_MAX_PATH) + 1;

    SERVER_START_REQ(create_namedMutex)
    {
        req->requestPid = GetCurrentProcessId();
        add_request_data(req, (const wchar_t *)name, Length * sizeof(wchar_t));
        ec = InvokeRequest(central_call, req);
        if (SUCCEEDED(ec)) {
            *pbAlreadyExists = reply->bAlreadyExisted;
            *pOid = reply->oid;
        }
    }
    SERVER_END_REQ;

    return ec;
}

// ------------ For CEvent ------------------------
CARAPI CPseudoCentral::CreateNamedEvent(
        /* [in]  */ WString name,
        /* [in]  */ Boolean bManualReset,
        /* [in]  */ EventState initialState,
        /* [out] */ Boolean * pbAlreadyExisted,
        /* [out] */ oid_t * pOid)
{
    ECode ec = NOERROR;

    assert(!name.IsNullOrEmpty());
    assert(NULL != pbAlreadyExisted);
    assert(NULL != pOid);

    Int32 Length = name.GetLength(AURA_MAX_PATH) + 1;

    SERVER_START_REQ(create_namedEvent)
    {
        req->requestPid = GetCurrentProcessId();
        req->bManualReset = bManualReset;
        req->initialState = initialState;
        add_request_data(req, (const wchar_t *)name, Length * sizeof(wchar_t));
        ec = InvokeRequest(central_call, req);
        if (SUCCEEDED(ec)) {
            *pbAlreadyExisted = reply->bAlreadyExisted;
            *pOid = reply->oid;
        }
    }
    SERVER_END_REQ;

    return ec;
}

CARAPI CPseudoCentral::TrywaitNamedEvent(
        /* [in]  */ oid_t oid,
        /* [in]  */ Millisecond32 msTimeOut,
        /* [out] */ WaitResult * pResult,
        /* [out] */ EventState * pState)
{
    ECode ec = NOERROR;

    assert(NULL != pResult);

    SERVER_START_REQ(trywait_namedEvent)
    {
        req->oid = oid;
        req->msTimeOut = msTimeOut;
        ec = InvokeRequest(central_call, req);
        if (SUCCEEDED(ec)) {
            *pResult = reply->result;
            if (pState)
                *pState  = reply->state;
        }
    }
    SERVER_END_REQ;

    return ec;
}

CARAPI CPseudoCentral::NotifyNamedEvent(
        /* [in]  */ oid_t oid,
        /* [in]  */ EventState state)
{
    ECode ec = NOERROR;

    SERVER_START_REQ(notify_namedEvent)
    {
        req->oid   = oid;
        req->state = state;
        ec = InvokeRequest(central_call, req);
    }
    SERVER_END_REQ;

    return ec;
}

CARAPI CPseudoCentral::ClearNamedEvent(
        /* [in]  */ oid_t oid)
{
    ECode ec = NOERROR;

    SERVER_START_REQ(clear_namedEvent)
    {
        req->oid = oid;
        ec = InvokeRequest(central_call, req);
    }
    SERVER_END_REQ;

    return ec;
}

ECode CPseudoCentral::Condition_Create(
        /* [in] */ WString name,
        /* [in] */ Boolean * pbAlreadyExisted,
        /* [out] */ oid_t * pOid)
{
    ECode ec = NOERROR;

    assert(!name.IsNullOrEmpty());
    assert(NULL != pbAlreadyExisted);
    assert(NULL != pOid);

    Int32 Length = name.GetLength(AURA_MAX_PATH) + 1;

    SERVER_START_REQ(condition_create)
    {
        req->requestPid = GetCurrentProcessId();
        add_request_data(req, (const wchar_t *)name, Length * sizeof(wchar_t));
        ec = InvokeRequest(central_call, req);
        if (SUCCEEDED(ec)) {
            *pbAlreadyExisted = reply->bAlreadyExisted;
            *pOid = reply->oid;
        }
    }
    SERVER_END_REQ;

    return ec;
}

ECode CPseudoCentral::Condition_Wait(
        /* [in] */ oid_t oid,
        /* [in] */ Millisecond32 msTimeOut,
        /* [out] */ WaitResult * pResult)
{
    ECode ec = NOERROR;

    assert(NULL != pResult);
    assert((msTimeOut > 0) || (INFINITE == msTimeOut));

    SERVER_START_REQ(condition_wait)
    {
        req->oid = oid;
        req->msTimeOut = msTimeOut;
        ec = InvokeRequest(central_call, req);
        if (SUCCEEDED(ec)) {
            *pResult = reply->result;
        }
    }
    SERVER_END_REQ;

    return ec;
}

ECode CPseudoCentral::Condition_Pulse(
        /* [in] */ oid_t oid)
{
    ECode ec = NOERROR;

    SERVER_START_REQ(condition_pulse)
    {
        req->oid   = oid;
        ec = InvokeRequest(central_call, req);
    }
    SERVER_END_REQ;

    return ec;
}

ECode CPseudoCentral::Condition_PulseAll(
        /* [in] */ oid_t oid)
{
    ECode ec = NOERROR;

    SERVER_START_REQ(condition_pulseall)
    {
        req->oid = oid;
        ec = InvokeRequest(central_call, req);
    }
    SERVER_END_REQ;

    return ec;
}

// ------------ For SharedMemory ------------------
CARAPI CPseudoCentral::CreateSharedMemory(
            /* [in]  */ WString name,
            /* [in]  */ MemorySize size,
            /* [in]  */ Boolean bCommit,
            /* [out] */ Boolean * pbAlreadyExisted,
            /* [out] */ oid_t * pOid)
{
    ECode ec = NOERROR;

    assert(!name.IsNullOrEmpty());
    assert(NULL != pbAlreadyExisted);
    assert(NULL != pOid);

    Int32 length = name.GetLength(AURA_MAX_PATH) + 1;

    SERVER_START_REQ(create_sharedmemory)
    {
        req->requestPid = GetCurrentProcessId();
        req->memorySize = size;
        req->bCommit = bCommit;
        add_request_data(req, (const wchar_t *)name, length * sizeof(wchar_t));
        ec = InvokeRequest(central_call, req);
        if (SUCCEEDED(ec)) {
            *pbAlreadyExisted = reply->bAlreadyExisted;
            *pOid = reply->oid;
        }
    }
    SERVER_END_REQ;

    return ec;
}

CARAPI CPseudoCentral::AddRefNamedObject(
            /* [in]  */ oid_t oid)
{
    ECode ec = NOERROR;

    SERVER_START_REQ(addref_namedobject)
    {
        req->requestPid = GetCurrentProcessId();
        req->oid = oid;
        ec = InvokeRequest(central_call, req);
    }
    SERVER_END_REQ;

    return ec;
}

CARAPI CPseudoCentral::ReleaseNamedObject(
            /* [in]  */ oid_t oid)
{
    ECode ec = NOERROR;

    SERVER_START_REQ(release_namedobject)
    {
        req->requestPid = GetCurrentProcessId();
        req->oid = oid;
        ec = InvokeRequest(central_call, req);
    }
    SERVER_END_REQ;

    return ec;
}

// ----------- For Service -----------------------

CARAPI CPseudoCentral::SrvcRegister(
    /* [in] */ PEMuid pClsId,
    /* [in] */ PEIID pIid,
    /* [in] */ UInt32 uIndex,
    /* [out]*/ oid_t * pOid)
{
    ECode ec = NOERROR;

    assert(NULL != pOid);
    SERVER_START_REQ(register)
    {
        req->processId = GetCurrentProcessId();
        req->clsid = *pClsId;
        req->iid = *pIid;
        req->uIndex = uIndex;
        ec = InvokeRequest(central_call, req);
        if (SUCCEEDED(ec))
            *pOid = reply->oid;
    }
    SERVER_END_REQ;

    return ec;
}

CARAPI CPseudoCentral::SrvcUnregister(
    /* [in] */ oid_t oid)
{
    ECode ec = NOERROR;

    SERVER_START_REQ(unregister)
    {
        req->processId = GetCurrentProcessId();
        req->oid = oid;
        ec = InvokeRequest(central_call, req);
    }
    SERVER_END_REQ;

    return ec;
}

CARAPI CPseudoCentral::SrvcRegisterCommon(
    /* [in] */ WString srvName,
    /* [in] */ PEMuid pClsId,
    /* [in] */ PEIID pIid,
    /* [in] */ UInt32 uIndex,
    /* [out]*/ oid_t * pOid)
{
    ECode ec = NOERROR;

    assert(!srvName.IsNullOrEmpty());
    assert(NULL != pOid);

    Int32 length = srvName.GetLength(MAX_SERVICE_NAME) + 1;

    SERVER_START_REQ(register_common)
    {
        req->processId = GetCurrentProcessId();
        req->clsid = *pClsId;
        req->iid = *pIid;
        req->uIndex = uIndex;
        add_request_data(req, (const wchar_t *)srvName, length * sizeof(wchar_t));
        ec = InvokeRequest(central_call, req);
        if (SUCCEEDED(ec))
            *pOid = reply->oid;
    }
    SERVER_END_REQ;

    return ec;
}

CARAPI CPseudoCentral::SrvcUnregsiterCommon(
    /* [in] */ WString srvName)
{
    ECode ec = NOERROR;

    assert(!srvName.IsNullOrEmpty());

    Int32 length = srvName.GetLength(MAX_SERVICE_NAME) + 1;

    SERVER_START_REQ(unregister_common)
    {
        req->processId = GetCurrentProcessId();
        add_request_data(req, (const wchar_t *)srvName, length * sizeof(wchar_t));
        ec = InvokeRequest(central_call, req);
    }
    SERVER_END_REQ;

    return ec;
}

CARAPI CPseudoCentral::SrvcResolveCommon(
    /* [in] */ WString srvName,
    /* [out]*/ ProcessId * pProcessId,
    /* [out]*/ ObjectType * pType,
    /* [out]*/ oid_t * pOid,
    /* [out]*/ EMuid * pClsId,
    /* [out]*/ UInt32 * pUIndex)
{
    ECode ec = NOERROR;

    assert(!srvName.IsNullOrEmpty());
    assert(NULL != pProcessId);
    assert(NULL != pType);
    assert(NULL != pOid);
    assert(NULL != pClsId);
    assert(NULL != pUIndex);

    Int32 length = srvName.GetLength(MAX_SERVICE_NAME) + 1;

    SERVER_START_REQ(resolve_common)
    {
        add_request_data(req, (const wchar_t *)srvName, length * sizeof(wchar_t));
        ec = InvokeRequest(central_call, req);
        if (SUCCEEDED(ec)) {
            *pProcessId =  reply->processId;
            *pType = reply->type;
            *pOid  = reply->oid;
            *pClsId = reply->clsid;
            *pUIndex = reply->uIndex;
        }
    }
    SERVER_END_REQ;

    return ec;
}

CARAPI CPseudoCentral::AttachImportService(
    /* [in] */ oid_t oid)
{
    ECode ec = NOERROR;

    SERVER_START_REQ(attach_service)
    {
        req->processId = GetCurrentProcessId();
        req->oid = oid;
        ec = InvokeRequest(central_call, req);
    }
    SERVER_END_REQ;

    return ec;
}

CARAPI CPseudoCentral::DetachImportService(
    /* [in] */ oid_t oid)
{
    ECode ec = NOERROR;

    SERVER_START_REQ(detach_service)
    {
        req->processId = GetCurrentProcessId();
        req->oid = oid;
        ec = InvokeRequest(central_call, req);
    }
    SERVER_END_REQ;

    return ec;
}

CARAPI CPseudoCentral::SrvcGetChannelName(
    /* [in] */ oid_t oid,
    /* [out]*/ WStringBuf * name)
{
    ProcessId processId = AURA_INVALID_PID;
    ECode ec = NOERROR;
    assert (name->GetCapacity());

    SERVER_START_REQ(get_process_id)
    {
        req->oid = oid;
        ec = InvokeRequest(central_call, req);
        if (SUCCEEDED(ec)) {
            processId = reply->processId;
        }
    }
    SERVER_END_REQ;

    if (FAILED(ec)) {
        return ec;
    }
    name->Append((Int32)processId);
    return ec;
}

CARAPI CPseudoCentral::SrvcRegisterService(
    /* [in] */ WString srvName,
    /* [in] */ oid_t oid)
{
    ECode ec = NOERROR;

    assert(!srvName.IsNullOrEmpty());
    Int32 length = srvName.GetLength(MAX_SERVICE_NAME) + 1;

    SERVER_START_REQ(register_service)
    {
        req->processId = GetCurrentProcessId();
        req->oid = oid;
        add_request_data(req, (const wchar_t *)srvName, length * sizeof(wchar_t));
        ec = InvokeRequest(central_call, req);
    }
    SERVER_END_REQ;

    return ec;
}

CARAPI CPseudoCentral::SrvcWaitService(
    /* [in]  */ WString srvName,
    /* [in]  */ Millisecond32 msTimeout,
    /* [out] */ WaitResult * pResult)
{
    ECode ec = NOERROR;
    assert(!srvName.IsNullOrEmpty());
    assert(NULL != pResult);
    Int32 length = srvName.GetLength(MAX_SERVICE_NAME) + 1;

    SERVER_START_REQ(wait_service)
    {
        req->msTimeout = msTimeout;
        add_request_data(req, (const wchar_t *)srvName, length * sizeof(wchar_t));
        ec = InvokeRequest(central_call, req);
        if (SUCCEEDED(ec)) {
            *pResult = reply->result;
        }
    }
    SERVER_END_REQ;

    return ec;
}
